package com.quan.sso.web.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.quan.common.base.annotation.Log;
import com.quan.common.base.bean.ResultBean;
import com.quan.common.base.enums.LogType;
import com.quan.common.biz.support.BaseController;
import com.quan.common.utils.DateUtils;
import com.quan.common.utils.JwtTokenUtils;
import com.quan.common.utils.PasswordUtils;
import com.quan.common.utils.RedisOperator;
import com.quan.sso.fegin.SystemUserService;
import com.quan.system.entity.SystemPermission;
import com.quan.system.entity.SystemRole;
import com.quan.system.entity.SystemUser;
import com.quan.system.model.LoginUserDto;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;

@RestController
@RequestMapping("/sso")
public class SSOContoller extends BaseController {

	@Autowired
	private SystemUserService systemUserService;

	@Autowired
	private RedisOperator redisOperator;

	/**
	 * JwtToken秘钥
	 */
	@Value("${jwt.secret:123456}")
	private String jwtSecret;

	/**
	 * JwtToken过去时间（秒）
	 */
	@Value("${jwt.timeout:1800}")
	private Long timeout;

	@Log(type=LogType.LOGIN)
	@PostMapping("/login")
	public ResultBean login(@RequestBody LoginUserDto login) {

		ResultBean resultBean = this.systemUserService.findByAccount(login.getAccount());

		if (resultBean.getFlag()) {
			SystemUser user = JSON.parseObject(JSON.toJSONString(resultBean.getData()), SystemUser.class);
			// 判断账号是否锁定
			if (!user.getStatus()) {
				return ResultBean.failure("账号已锁定，请联系管理员！");
			}
			// 验证密码是否正确
			if (!PasswordUtils.isPasswordValid(user.getPassword(), login.getPassword(), user.getSalt())) {
				return ResultBean.failure("密码不正确！");
			}
			user.setPassword(null);

			// 获取用户角色
			ResultBean resultBeanRole = this.systemUserService.findRolesByUserId(user.getId());
			List<SystemRole> roles = JSON.parseArray(JSON.toJSONString(resultBeanRole.getData()), SystemRole.class);

			// 获取用户权限
			ResultBean resultBeanPermission = this.systemUserService.findPermissionsByUserId(user.getId());
			List<SystemPermission> permissions = JSON.parseArray(JSON.toJSONString(resultBeanPermission.getData()), SystemPermission.class);
			List<String> pagePermission = new ArrayList<String>(); // 页面访问权限
			List<String> actionPermission = new ArrayList<String>(); // 操作权限
			for (SystemPermission SystemPermission : permissions) {
				if (null != SystemPermission.getType() && SystemPermission.getType().equals("1")) { // 页面类型
					pagePermission.add(SystemPermission.getPermission());
				} else {
					actionPermission.add(SystemPermission.getPermission());
				}
			}

			Map<String, Object> claims = new HashMap<String, Object>();
			claims.put("sub", user.getAccount());
			claims.put("ctime", DateUtils.getMillis(new Date()));
			claims.put("exp", DateUtils.addMinute(timeout.intValue()));
			claims.put("user", user);
			claims.put("userId", user.getId()+"");
			claims.put("account", user.getAccount());
			claims.put("realName", user.getRealName());
			claims.put("isAdmin", user.getSuperAdmin());
			claims.put("roles", roles);
			claims.put("pagePermission", pagePermission);
			claims.put("actionPermission", actionPermission);
			
			// 生成JWT Token
			String token = JwtTokenUtils.createToken(claims, jwtSecret);

			// 将Token 保存到Redis缓存中
			this.redisOperator.set("sso:token:" + user.getId(), token, timeout);
			
			return ResultBean.ok("登录成功", token);
		}
		return resultBean;
	}
	
	@Log(type=LogType.LOGOUT)
	@GetMapping("/logout")
	public boolean logout() {
		String token = this.request.getHeader("Auth-Token");

		// Token为空，缓存中已没有改用户数据
		if (null == token || "".equals(token.trim())) {
			return true;
		}

		Jws<Claims> parse = JwtTokenUtils.parse(token, jwtSecret);
		if (null != parse) {
			Claims body = parse.getBody();

			this.redisOperator.del("sso:token:" + body.get("userId"));
			return true ;
		} else {
			logger.info("Token解析失败");
			return false;
		}
	}
	
	@GetMapping("/validToken")
	public boolean validToken() {
		String token = this.request.getHeader("Auth-Token");
		
		// Token为空
		if (null == token || "".equals(token.trim())) {
			return false;
		}
		
		Jws<Claims> parse = JwtTokenUtils.parse(token, jwtSecret);
		if (null != parse) {
			Claims body = parse.getBody();
			boolean hasKey = this.redisOperator.hasKey("sso:token:" + body.get("userId"));
			if(hasKey) {
				this.redisOperator.expire("sso:token:" + body.get("userId"), timeout);
				return true ;
			} else {
				return false ;
			}
		} else {
			logger.info("Token解析失败");
			return false;
		}
	}

}
